package com.fengwk.support.util;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.fengwk.support.exception.BaseException;
import com.fengwk.support.util.LoggerUtils.Logger;

/**
 * 用于结果对象输出
 */
public class ResultUtils {

	private static final Logger LOG = LoggerUtils.getLogger(ResultUtils.class);
	
	public static final String RESULT_KEY_CODE = ResultUtils.class + "RESULT_KEY_CODE";
	public static final String RESULT_KEY_RESULT = ResultUtils.class + "RESULT_KEY_RESULT";
	
	// 结果标识码
	public static long UNKNOWN_ERROE_CODE = -1L;// 未知错误
	public static long FAIL_CODE = 0L; // 失败
	public static long SUCCESS_CODE = 1L;// 成功
	public static long SYSTEM_ERROE_CODE = 2L;// 系统错误
	public static long METHOD_DEFINE_CODE = 3L;// 接口错误
	public static long PARAMETER_ERROR_CODE = 4L;// 参数错误
	
	public static String RESULT_KEY = RESULT_KEY_CODE;

	// ThreadLocal
	private static final ThreadLocal<JsonMap> JSON_MAP_THREAD_LOCAL = new ThreadLocal<JsonMap>();

	private ResultUtils() {
		throw new BaseException("can not instance " + getClass());
	}
	
	/**
	 * 置入结果码
	 * 
	 * @param code
	 */
	public static void setCode(Long code) {
		JsonMap jsonMap = getCurrentJsonMap();
		if (RESULT_KEY == RESULT_KEY_CODE) {
			jsonMap.setCode(code);
		} else if (RESULT_KEY == RESULT_KEY_RESULT) {
			jsonMap.setResult(code);
		}
	}

	/**
	 * 置入结果信息
	 * 
	 * @param msg
	 */
	public static void setMessage(String msg) {
		getCurrentJsonMap().setMsg(msg);
	}

	/**
	 * 置入结果数据对象
	 * 
	 * @param data
	 */
	public static void setData(Object data) {
		getCurrentJsonMap().setData(data);
	}

	/**
	 * 置入 key value 属性
	 * 
	 * @param key
	 * @param value
	 */
	public static void setAttribute(String key, Object value) {
		getCurrentJsonMap().setAttribute(key, value);
	}

	/**
	 * 置入属性集
	 * 
	 * @param attrs
	 */
	public static void setAttributes(Map<String, Object> attrs) {
		getCurrentJsonMap().setAttrs(attrs);
	}

	/**
	 * 清除结果码
	 */
	public static void clearResult() {
		if (RESULT_KEY == RESULT_KEY_CODE) {
			getCurrentJsonMap().clearCode();
		} else if (RESULT_KEY == RESULT_KEY_RESULT) {
			getCurrentJsonMap().clearResult();
		}
	}

	/**
	 * 清除结果信息
	 */
	public static void clearMessage() {
		getCurrentJsonMap().clearMsg();
	}

	/**
	 * 清除结果数据
	 */
	public static void clearData() {
		getCurrentJsonMap().clearData();
	}

	/**
	 * 清除属性
	 * 
	 * @param key
	 */
	public static void removeAttribute(String key) {
		getCurrentJsonMap().removeAttribute(key);
	}

	/**
	 * 清除所有属性
	 */
	public static void clearAttributes() {
		getCurrentJsonMap().clearAttrs();
	}

	/**
	 * 获取对象形式的结果
	 * 
	 * @return
	 */
	public static Object getObjectResult() {
		Object resObj = getCurrentJsonMap();
		removeCurrentJsonMap();
		return resObj;
	}

	/**
	 * 获取json格式的结果对象
	 * 
	 * @return
	 */
	public static String getJsonResult() {
		return JsonUtils.toJson(getObjectResult());
	}

	/**
	 * 以json/jsonp形式返回结果对象
	 * 
	 * @param response
	 */
	public static void returnJsonResult(HttpServletRequest request, HttpServletResponse response) {
		returnJsonResult(request, response, getJsonResult());
	}
	
	private static void returnJsonResult(HttpServletRequest request, HttpServletResponse response, String json) {
		String jsonpCallBack = WebUtils.getJsonpCallBack(request);
		if (StringUtils.isNotBlank(jsonpCallBack)) {
			WebUtils.returnJsonpResponse(response, json, jsonpCallBack);
			return;
		}
		WebUtils.returnJsonResponse(response, json);
	}

	/**
	 * 以json形式返回结果对象
	 * 
	 * @param response
	 * @param obj 
	 */
	public static void returnJsonResult(HttpServletRequest request, HttpServletResponse response, Object obj) {
		returnJsonResult(request, response, returnJsonResult(obj));
	}

	/**
	 * 以json形式返回结果对象
	 * 
	 * @param response
	 * @param obj
	 * @param msg 文本返回信息
	 */
	public static void returnJsonResult(HttpServletRequest request, HttpServletResponse response, Object obj, String msg) {
		returnJsonResult(request, response, returnJsonResult(obj, msg));
	}
	
	public static String returnJsonResult(Object obj) {
		return returnJsonResult(obj, null);
	}
	
	public static String returnJsonResult(Object obj, String msg) {
		long code = SUCCESS_CODE;
		ResultUtils.setData(obj);
		ResultUtils.setCode(code);
		ResultUtils.setMessage(msg);
		return getJsonResult();
	}

	// 获取当前线程的jsonMap
	private static JsonMap getCurrentJsonMap() {
		JsonMap jsonMap = JSON_MAP_THREAD_LOCAL.get();
		if (jsonMap == null) {
			jsonMap = new JsonMap();
			JSON_MAP_THREAD_LOCAL.set(jsonMap);
		}
		return jsonMap;
	}

	// 释放当前线程的jsonMap
	private static void removeCurrentJsonMap() {
		JSON_MAP_THREAD_LOCAL.remove();
	}
	
	public static Object decodeJsonMapData(String jsonMapStr, Type type) {
	    LOG.debug("decodeJsonMap " + jsonMapStr);
		if (StringUtils.isNotBlank(jsonMapStr) && !"void".equals(type.getTypeName())) {
			JsonMap jsonMap = JsonUtils.fromJson(jsonMapStr, JsonMap.class);
			return decodeJsonMapData(jsonMap, type);
		}
		return null;
	}
	
	public static Object decodeJsonMapData(JsonMap jsonMap, Type type) {
		if (jsonMap != null && type != null) {
			Long code = jsonMap.getCode();
			if (code == null || code != SUCCESS_CODE) {
			    LOG.error("jsonMap error " + JsonUtils.toJson(jsonMap));
			}
			Class<?> typeClass = null;
			if (type.getClass() == Class.class) {
				typeClass = (Class<?>) type;
			} else {
				typeClass = (Class<?>) ((ParameterizedType) type).getRawType();
			}
			if (typeClass != null && TypeUtils.isCollection(typeClass)) {
				Type[] ts = ((ParameterizedType) type).getActualTypeArguments();
				if (ts != null && ts.length > 0) {
					return jsonMap.getDataToList((Class<?>) ts[0]);
				}
			} else {
				return jsonMap.getData(typeClass);
			}
		}
		return null;
	}
	
	/**
	 * JsonMap
	 */
	public static class JsonMap implements Serializable {
		
		private static final long serialVersionUID = 5635995673444801403L;
		
		private Long code;
		private Long result;
		private String msg;
		private Object data;
		private Map<String, Object> attrs;

		private JsonMap() {}
		
		public Long getCode() {
			if (RESULT_KEY == RESULT_KEY_RESULT) {
				return result;
			}
			return code;
		}

		public String getMsg() {
			return msg;
		}

		public Object getData() {
			return data;
		}
		
		/**
		 * 获取json反序列化对象
		 * 
		 * @param clazz 映射字节码
		 * @return
		 */
		@SuppressWarnings("unchecked")
		public <T> T getData(Class<T> clazz) {
			if (data == null) {
				return null;
			}
			String dataStr = JsonUtils.toJson(data);
			if (TypeUtils.isType(clazz, String.class)) {
				return (T) dataStr;
			}
			return JsonUtils.fromJson(dataStr, clazz);
		}
		
		/**
		 * 获取json反序列化List对象
		 * 
		 * @param generic
		 * @return
		 */
		public <G> List<G> getDataToList(Class<G> generic) {
			return JsonUtils.parseLinkedTreeMapToList((Collection<?>) data, generic);
		}

		public Map<String, Object> getAttrs() {
			return attrs;
		}

		public void setAttrs(Map<String, Object> attrs) {
			this.attrs = attrs;
		}
		
		public void setCode(Long code) {
			this.code = code;
		}
		
		public void setResult(Long result) {
			this.result = result;
		}

		public void setMsg(String msg) {
			this.msg = msg;
		}

		public void setData(Object data) {
			this.data = data;
		}

		public void clearCode() {
			code = null;
		}
		
		public void clearResult() {
			result = null;
		}

		public void clearMsg() {
			msg = null;
		}

		public void clearData() {
			data = null;
		}

		public void clearAttrs() {
			attrs = null;
		}

		public Object getAttribute(String key) {
			if (attrs == null) {
				return null;
			}
			return attrs.get(key);
		}

		public void setAttribute(String key, Object value) {
			if (attrs == null) {
				attrs = new HashMap<String, Object>();
			}
			attrs.put(key, value);
		}

		public void removeAttribute(String key) {
			if (attrs != null) {
				attrs.remove(key);
			}
		}

	}

}
